package com.kanan.vueupload.service;

import com.kanan.vueupload.entity.MultipartFileParamEntity;
import com.kanan.vueupload.utils.MultipartFileUploadUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author kananan
 * @date 2021/1/17
 */
@Service
public class FileManagerService {

    @Autowired
    private MultipartFileUploadUtils multipartFileUploadUtils;

//    @Value("${filePath.tempWorkBasePath}")
    private String tempWorkPath;//分片临时文件存放目录
//    @Value("${filePath.saveFileBasePath}")
    private String saveFilePath;//文件存放目录
    private ReentrantLock filetempLock = new ReentrantLock();


    public void saveMutiBurstFiletoDir(MultipartFileParamEntity fileinfo, MultipartFile file) throws Exception {
        this.checkBaseDir(tempWorkPath);
        File tempFile = this.GenerateDirPathForCurrFile(fileinfo, "chunks");
        multipartFileUploadUtils.spaceFileWriter(file, tempFile, fileinfo);
    }


    public void saveSingleFiletoDir(MultipartFileParamEntity fileinfo, MultipartFile file) throws Exception {
        this.checkBaseDir(saveFilePath);
        File targetFile = this.GenerateDirPathForCurrFile(fileinfo, "single");
        multipartFileUploadUtils.saveFile2DirPath(file, targetFile);
    }


    synchronized public File GenerateDirPathForCurrFile(MultipartFileParamEntity fileinfo, String flag) throws Exception {
        String fileName = fileinfo.getFilename();
//        String lastModifiedDate = fileinfo.getLastModifiedDate();
        String lastModifiedDate = "";
        long fileSize = fileinfo.getTotalSize();
//        String type = fileinfo.getType();
        String type = "";
        String id = fileinfo.getIdentifier();
        String extName = fileName.substring(fileName.lastIndexOf("."));
        long timeStemp = System.currentTimeMillis();
        if ("single".equals(flag)) {
            String fileNameSource = fileName + lastModifiedDate + fileSize + type + id + timeStemp;
            String fileDirName = fileNameSource + extName;
            File targetFile = new File(saveFilePath, fileDirName);
            while (targetFile.exists()) {
                fileNameSource = fileNameSource + "1";
                fileDirName = fileNameSource + extName;
                targetFile = new File(fileDirName);
            }
            return targetFile;
        } else if ("chunks".equals(flag)) {
            String fileNameSource = fileSize + "_" + fileName + id + lastModifiedDate;
            String fileDirName = tempWorkPath + "/" + fileNameSource + extName + ".temp";
            File tempFile = new File(fileDirName);//禁用FileInfo.exists()类, 防止缓存导致并发问题
            if (!(tempFile.exists() && tempFile.isFile())) {
                filetempLock.lock();//上锁
                if (!(tempFile.exists() && tempFile.isFile())) {
                    multipartFileUploadUtils.readySpaceFile(fileinfo, tempFile);
                }
                filetempLock.unlock();//释放锁
            }
            tempFile = new File(fileDirName);
            return tempFile;
        } else {
            throw new Exception("目标文件生成失败");
        }
    }

    public void checkBaseDir(String baseDir) throws Exception {
        File file = new File(baseDir);
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
    }

    //利用RandomAccessFile实现文件的随机读写。从而实现在分片上传时直接覆盖空白文件中的一小段数据，从而避免分片保存为临时文件再合并的IO消耗，
    //文件合并
    public void MultipartFileMergingChunks(MultipartFileParamEntity fileinfo) throws Exception {
        // TODO Auto-generated method stub
        String fileName = fileinfo.getFilename();
//        String lastModifiedDate = fileinfo.getLastModifiedDate();
        String lastModifiedDate = "";
        long fileSize = fileinfo.getTotalSize();
        String id = fileinfo.getIdentifier();
        String extName = fileName.substring(fileName.lastIndexOf("."));
        String fileNameSource = fileSize + "_" + fileName + id + lastModifiedDate;
        String fileDirName = tempWorkPath + "/" + fileNameSource + extName + ".temp";
        File tempFile = new File(fileDirName);
        if (tempFile.exists() && tempFile.isFile()) {
            checkBaseDir(saveFilePath);
            String targetDirName = saveFilePath + "/" + fileNameSource;
            File targetFile = new File(targetDirName + extName);
            while (targetFile.exists() && targetFile.isFile()) {
                targetDirName = targetDirName + "1";
                targetFile = new File(targetDirName + extName);
            }
            System.out.println(targetFile.getAbsolutePath());
            if (tempFile.renameTo(targetFile)) {
                System.out.println("文件重命名成功!");
                //数据库操作
                //数据库操作
            } else {
                System.out.println("文件重命名失败!");
                throw new Exception("临时文件重命名失败");
            }

        }
    }
}
